// 缓冲区

#ifndef _M_BUFFER_H__
#define _M_BUFFER_H__

#include <cassert>
#include <vector>

namespace snowdragon
{
#define BUFFER_DAFAULT_SIZE (1 * 1024 * 1024)           // 缓冲区默认大小
#define BUFFER_THRESHOLD_SIZE (10 * 1024 * 1024)        // 缓冲区阈值
#define BUFFER_LINEAR_INCREMENT (1 * 1024 * 1024)       // 缓冲区大小超过阈值后，进行线性递增的大小

    class Buffer
    {
    public:
        Buffer()
            : _buffer(BUFFER_DAFAULT_SIZE), _reader_index(0) // 统一在此处初始化
            , _writer_index(0)
        {}
        size_t readableSize()               // 获取可读大小
        {
            return _writer_index - _reader_index;
        }
        size_t writeableSize()              // 获取可写大小
        {
            return _buffer.size() - _writer_index;
        }
        void push(const char *data, size_t len)     // 压入数据
        {
            // assert(len <= writeableSize());
            ensureSufficient(len);              // 扩容
            std::copy(data, data + len, &_buffer[_writer_index]);       // 将对应数据拷贝到缓冲区，即压入数据
            _writer_index += len;               // 记得自增，修改可写位置，方便下次写入
        }
        void pop(size_t len)                    // 弹出数据，即数据被取走了，需要从缓冲区"删除"
        {
            // assert(len <= readableSize());
            // _reader_index += len;
            _reader_index += len;                   // 已经读走数据，下次读取的位置有偏移
            assert(_reader_index <= _writer_index);     // 取走的数据不能大于可取的大小，否则就报错结束。先加还是后加也就无所谓了
        }
        const char *begin()         // 获取读取位置
        {
            return &_buffer[_reader_index];
        }
        bool empty()            // 判断缓冲区是否还有数据
        {
            return _reader_index == _writer_index;
        }
        void reset()            // 重置，双缓冲区交换时，需要将读取和写入的下标复原为0，方便缓冲区的压入数据操作
        {
            _reader_index = _writer_index = 0;
        }
        void swap(Buffer &buff)         // 交换缓冲区，主要用在双缓冲区的交换操作中
        {
            // std::swap(_buffer, buff._buffer);
            _buffer.swap(buff._buffer);         // 直接用容器有的交换函数
            std::swap(_reader_index, buff._reader_index);
            std::swap(_writer_index, buff._writer_index);
        }

    private:
        // 扩容，但异步任务处理器的安全模式为安全时，会直接返回。不安全时才会扩容
        void ensureSufficient(int len)
        {
            // if(_writer_index + len >= writeableSize())  return;
            // writeableSize是可写大小，不要加上_writer_index，当其（len）小于或等于时
            // 才返回，不要搞反了，不然数据会有一些写不了，即丢失
            if (len <= writeableSize())             
                return;
            size_t new_size = _buffer.size();
            while (new_size <= _writer_index + len)         // 确保新大小，即扩容的大小是足够的
            {
                // 是小于，不要写成大于，阈值BUFFER_THRESHOLD_SIZE前才是翻倍增长
                if (_buffer.size() < BUFFER_THRESHOLD_SIZE)
                    new_size = new_size * 2;                // 小于阈值，双倍扩容
                else
                    new_size = new_size + BUFFER_LINEAR_INCREMENT;      // 大于阈值，线性扩容
            }
            _buffer.resize(new_size);           // 扩容
        }

    private:
    // public:          // 调式使用对应的成员变量时需要是公共的访问权限
        size_t _reader_index;           // 读取位置下标
        size_t _writer_index;           // 写入位置下标
        std::vector<char> _buffer;      // 保存数据
    };
}

#endif